/*
 * 计划任务更新模块 V0.2
 * 将一个任务插入有序数组，倒序排列。
 * 取出最近的执行任务
 * 作者:basncy c@basncy.com * 
 */

#include "usbctrl.h"
#include "../include/uptaskp.h"

static pthread_mutex_t	 uptaskpmutex;	/*  锁 */
static struct uptaskp	*uptaskpptr;	/* 指向共享内存区的指针 */
static FILE *uptaskpfp;
/*
 * 初始化计划任务更新队列
 * 返回 0成功  -1失败
 */
int
initutp()
{
  struct uptaskp	data;
  /* 初始化计划任务数据 */
  size_t size=sizeof(struct uptaskp);

  if((uptaskpfp=fopen("uptaskp.data","r+")) == NULL){
    //        printf("文件不存在，使用初始化数据\n");
    uptaskpfp=fopen("uptaskp.data","a+");
    memset(&data, 0,size);
    data.utp_nexe = -1;
  }
  else{
    //printf("从文件中载入数据\n");
    fread(&data,size,1,fp);
  }
  //映射到内存
  uptaskpptr = (struct uptaskp *)mmap(NULL,size,PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1,0);
  memcpy(uptaskpptr,&data,size);
  
  //  printf("成功加载数据\n");
  
  /* 初始化互斥锁 */
  memset(&uptaskpmutex,0,sizeof(pthread_mutex_t));
  return 0;
}


/*
 * 添加计划任务。规则： etime从小到大排列，从数组尾开始插入数据
 * newcmd: 新任务
 * 返回 0成功 -1失败
 */
int
addutp(const struct upcmd newcmd)
{
  pthread_mutex_lock(&uptaskpmutex);

  struct upcmd	*ptr  =	uptaskpptr->utp_upcmds;
  size_t	 size =	sizeof(struct upcmd);
  int		 i;
  if((i = uptaskpptr->utp_nexe + 1) > 0){
    //    printf("已经有任务了，开始寻找插入点\n");
    do{
      if(ptr->etime > newcmd.etime)
	ptr ++;
      else{			//找到插入位置
	memmove(ptr+1,ptr,i*size);//移动的个数
	break;
      }
      i--;
    }while(i>0);
  }

  memcpy(ptr,&newcmd,size);
  uptaskpptr->utp_nexe++;
  
  pthread_mutex_unlock(&uptaskpmutex);

  return 0;
}

/*
 * 取出最近一次计划任务
 * cmd: 保存取出的任务
 * 返回： 0成功， -1失败
 */
int
getutp(struct upcmd *cmd)
{

  pthread_mutex_lock(&uptaskpmutex);


  int i;
  if((i=uptaskpptr->utp_nexe)<0){
    //printf("取出任务出错：没任务，任务队列异常\n");
    pthread_mutex_unlock(&uptaskpmutex);
    // printf("取出：已解锁，出错退出\n");
    return (-1);
  }
  else{
    // printf("取出utp_nexe: %d\n",i);
    memcpy(cmd,&uptaskpptr->utp_upcmds[i],sizeof(struct upcmd));
    uptaskpptr->utp_nexe--;
    }
  
 
  //  printf("取出后utp_nexe: %d\n",uptaskpptr->utp_nexe);
  //  msync(uptaskpptr,sizeof(struct uptaskp),MS_SYNC);
  

  pthread_mutex_unlock(&uptaskpmutex);
  // printf("取出：已解锁\n");
  return 0;
}


/* 遍历所有任务 */
int
allutp()
{
  int		 i   = 0;
  int		 n   = uptaskpptr->utp_nexe;
  struct upcmd	*ptr = uptaskpptr->utp_upcmds;
  //  printf("遍历：\n");
  while(i<=n){
    printf("%d\n",ptr->etime);
    ptr++;
    i++;
  }
  return (n+1);
}


/* 关闭计划任务 */
void
closeutp()
{
  pthread_mutex_lock(&uptaskpmutex);
  //  printf("写入数据到文件\n");
  //printf("fp: %d\n",fp);
  fseek(fp,0,SEEK_SET);
  fwrite(uptaskpptr,sizeof(struct uptaskp),1,uptaskpfp);
  pthread_mutex_unlock(&uptaskpmutex);
  fclose(uptaskpfp);
  munmap(uptaskpptr,sizeof(struct uptaskp));
  //printf("成功退出\n");
}
